Skip to content

feat: implement InventoryComponent for Epic 5.2#142

Merged
mcj-coder merged 3 commits into
mainfrom
feature/41-inventory-component-v2
Jan 19, 2026
Merged

feat: implement InventoryComponent for Epic 5.2#142
mcj-coder merged 3 commits into
mainfrom
feature/41-inventory-component-v2

Conversation

@martincjarvis

Copy link
Copy Markdown
Collaborator

Summary

Adds InventoryComponent for character inventory management with add, remove, and query operations. Enables characters to track materials with immutable operations following codebase patterns.

Issue

Closes #41

Changes

  • InventoryComponent sealed record with immutable operations
    • AddItem(materialId, quantity) - adds or increments material quantity
    • RemoveItem(materialId, quantity) - removes material with validation
    • GetQuantity(materialId) - retrieves current quantity (0 if not present)
    • HasSufficientQuantity(materialId, quantity) - checks availability
  • Internal dictionary tracks MaterialId → quantity mappings
  • Throws InvalidOperationException when removing insufficient quantity
  • Follows existing component patterns (ActiveCraft, ClassProgressCollection)

Testing

  • ✅ 11 comprehensive tests added
  • ✅ All 532 tests pass (444 Core + 88 Simulation)
  • ✅ Zero compiler warnings

Test Coverage

  • Empty inventory initialization
  • Adding new/existing materials
  • Removing materials (partial/complete)
  • Insufficient quantity validation
  • Multiple material tracking
  • Quantity checking helper

Test Output

$ dotnet test --verbosity quiet
Passed!  - Failed:     0, Passed:   444, Skipped:     0, Total:   444
Passed!  - Failed:     0, Passed:    88, Skipped:     0, Total:    88

Build Output

$ dotnet build --warnaserror
Build succeeded.
    0 Warning(s)
    0 Error(s)

Notes

This PR recreates the InventoryComponent work from the closed PR #140, now properly opened from the Contributor account (martincjarvis) as required by the workflow.

Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com

- Add InventoryComponent with AddItem, RemoveItem, GetQuantity methods
- Add HasSufficientQuantity helper for checking material availability
- Immutable record pattern following codebase conventions
- Comprehensive test coverage (11 tests) including edge cases

Refs #41
@github-actions

github-actions Bot commented Jan 19, 2026

Copy link
Copy Markdown
Messages
📖 ✅ Issue properly linked: Closes #41
📖 ✅ Summary section found
📖 ✅ PR title follows Conventional Commits format

Recommended Persona Reviews

💻 .NET Specialist - C# code changes detected

See docs/roles/ for persona details.


Danger analysis complete for feat: implement InventoryComponent for Epic 5.2. 3 files changed, 3 commits.

Generated by 🚫 dangerJS against edd83e5

@mcj-coder mcj-coder left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: Epic 5.2 - InventoryComponent

Strengths ✅

  • Clean immutable design using sealed record pattern
  • Complete test coverage (11 tests, all passing)
  • Zero warnings with --warnaserror
  • Clear API with intuitive methods
  • Proper error handling for insufficient quantities

Critical Issues ❌

1. Missing Equality Implementation

Location: InventoryComponent.cs

Problem: The sealed record doesn't override Equals() and GetHashCode() for proper dictionary comparison. Default record equality compares dictionary references, not contents.

Why critical: This will cause incorrect equality comparisons when two inventories with the same contents are compared, breaking state management and change detection.

Fix: Add custom Equals() and GetHashCode() following the pattern in ClassProgressCollection.cs (lines 162-188).

Important Issues ⚠️

2. Missing Input Validation

Location: InventoryComponent.cs:36, :48

Problem: Neither AddItem nor RemoveItem validate that quantity is positive. This allows negative quantities to bypass validation.

Fix: Add guard clauses:

if (quantity <= 0)
{
    throw new ArgumentOutOfRangeException(nameof(quantity), 
        "Quantity must be positive.");
}

Missing tests: Need tests for negative and zero quantity scenarios.

3. Missing GetAll() Method

Problem: No way to enumerate all materials in inventory. ClassProgressCollection provides GetAll() but InventoryComponent doesn't.

Why important: Future systems will need this for UI display, weight/value calculations, crafting material checks, and serialization.

Fix: Add:

public IReadOnlyDictionary<MaterialId, int> GetAll() => _items;

Minor Suggestions 💡

  • Add immutability test (verify operations return new instances)
  • Add HasSufficientQuantity edge case tests (zero/negative quantities)
  • Consider documenting capacity limits design decision

Assessment

Status: Request Changes

Verdict: Core design is excellent and aligns with project patterns. The Critical equality issue must be fixed to prevent state management bugs. Important issues (validation, GetAll) should also be addressed for completeness and future-proofing.

Next Steps: Fix the 3 key issues above, then this will be ready to merge.

… to InventoryComponent

Addresses code review feedback from PR #142:

1. Critical: Implement custom Equals() and GetHashCode()
   - Follows pattern from ClassProgressCollection (lines 162-188)
   - Compares dictionary contents, not references
   - Prevents state management bugs

2. Important: Add input validation for AddItem/RemoveItem
   - Validates quantity > 0 in both methods
   - Throws ArgumentOutOfRangeException for invalid quantities
   - Prevents negative quantities bypassing validation

3. Important: Add GetAll() method
   - Returns IReadOnlyDictionary<MaterialId, int>
   - Enables UI display, serialization, and material checks
   - Aligns with ClassProgressCollection pattern

Test coverage:
- 11 new tests for equality, validation, GetAll, and immutability
- All 456 tests passing, zero warnings

Refs #41
@martincjarvis

Copy link
Copy Markdown
Collaborator Author

Review Feedback Addressed

Thank you for the thorough review! I've implemented all three requested changes:

1. ✅ Custom Equality Implementation (Critical)

  • Added method following the pattern (lines 96-114)
  • Added method with ordered dictionary hashing (lines 116-125)
  • Tests confirm proper content-based equality comparison
  • Prevents state management bugs from reference comparison

2. ✅ Input Validation (Important)

  • Added guard clauses in both (lines 38-42) and (lines 56-60)
  • Validates quantity > 0, throws for invalid input
  • Prevents negative quantities bypassing validation
  • Added tests for zero and negative quantity scenarios

3. ✅ GetAll() Method (Important)

  • Added method returning (line 93)
  • Enables enumeration for UI, serialization, and crafting checks
  • Aligns with existing pattern

Additional Improvements

  • Added immutability tests verifying operations return new instances
  • All 456 tests passing, zero warnings
  • Commit: edd83e5

Ready for re-review!

@mcj-coder mcj-coder left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-Review: All Issues Addressed ✅

Excellent work addressing all the review feedback! The implementation now follows project patterns and is production-ready.

Changes Verified

1. ✅ Critical: Equality Implementation (lines 96-124)

  • Custom Equals() compares dictionary contents, not references
  • GetHashCode() uses ordered iteration for consistency
  • Follows ClassProgressCollection pattern exactly
  • Tests confirm equal inventories are detected correctly

2. ✅ Important: Input Validation (lines 38-41, 56-59)

  • Both AddItem and RemoveItem validate quantity > 0
  • Throws ArgumentOutOfRangeException for invalid values
  • Prevents negative quantities bypassing validation
  • Comprehensive test coverage for zero/negative cases

3. ✅ Important: GetAll() Method (line 93)

  • Returns IReadOnlyDictionary<MaterialId, int> as recommended
  • Enables UI display, serialization, and material checks
  • Aligns with ClassProgressCollection pattern
  • Tests verify correct behavior for empty and populated inventories

Test Coverage ✅

  • 22 total tests (11 original + 11 new)
  • Equality comparison (4 tests)
  • Input validation (4 tests)
  • GetAll() method (2 tests)
  • Immutability verification (2 tests)
  • All 456 tests passing, zero warnings

Quality Gates ✅

  • ✅ All CI checks passed
  • ✅ Zero compiler warnings
  • ✅ Clean build
  • ✅ Comprehensive test coverage
  • ✅ Follows project patterns

Status: Approved - Ready to merge!

Great job implementing the fixes methodically and thoroughly.

@mcj-coder
mcj-coder merged commit caf95a8 into main Jan 19, 2026
3 checks passed
@mcj-coder
mcj-coder deleted the feature/41-inventory-component-v2 branch January 19, 2026 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5.2 Implement InventoryComponent

2 participants